#! /bin/bash
export LANG=en_US.UTF-8

#WARNLIMIT=-1 		#警告值 超过该值则认为是需要告警
#ERRORLIMIT=-1 		#错误值 超过该值认为是错误

PORT=6379

CONN=0				#是否检查连接数
CONNMIN=
CONNMAX=
MEMORY=0			#是否检查内存
MEMORYMIN=
MEMORYMAX=
CPU=0				#是否检查CPU
CPUMIN=
CPUMAX=

SLOW_QUERY_MIN=
SLOW_QUERY_MAX=
SLOW_QUERY=

CURNUM=				#当前的性能参数

WranResultStr=		#最后形成的告警字符串
ErrorResultStr=		#最后形成的错误字符串
DataResultStr=		#性能呢个参数字符串
REDIS_STAT=

FLAGEID=
#是否输出FLAGPID
FLAGEOPID=1
#是否输出RUNTIME
RUNTIME=1
#是否输出STARTTIME
STARTTIME=0
VERBOSE=0

QUOTASTR=
quota=

#redis认证密码
AUTHEN=""
BASEDIR=/iflytek/redis-2.8.3
function gotErr(){
	if [ "$1" -eq 0 ];then
		echo "mailstatedes=各项指标恢复正常 statedes=各项指标恢复正常|$DataResultStr ${REDIS_STAT}${SLOW_RESULT}"
	elif [ "$1" -eq 1 ];then 
		echo "quota=${quota} mailstatedes=$WranResultStr statedes=$WranResultStr ${QUOTASTR} |$DataResultStr ${REDIS_STAT}${SLOW_RESULT}"
	elif [ "$1" -eq 2 ];then 
		if [[ "${WranResultStr}" != "" ]]; then
			echo "quota=${quota} mailstatedes=${WranResultStr},${ErrorResultStr} statedes=${WranResultStr},${ErrorResultStr} ${QUOTASTR}|$DataResultStr ${REDIS_STAT}${SLOW_RESULT}"
		else
			echo "quota=${quota} mailstatedes=${ErrorResultStr} statedes=${ErrorResultStr} ${QUOTASTR}|$DataResultStr ${REDIS_STAT} ${SLOW_RESULT}"
		fi
		
	elif [ "$1" -eq 3 ];then 
		echo "mailstatedes=无法获取到指标,疑似组件故障,请确认并请检查监控脚本和运维平台配置 statedes=无法获取到指标,疑似组件故障,请确认并请检查监控脚本和运维平台配置|$DataResultStr"
	fi

	exit $1
}

#返回是否服务是否存活
function isAlive(){
  FLAGEID=$(netstat -lnp | grep $PORT | grep LISTEN | grep 0.0.0.0 |grep -v "127.0.0.1"|awk '{for(i=1;i<=NF;i++){if($i ~ /redis-ser/) print $i}}'| awk -F '/' '{print $1}')
	isAliveStr=$(ps aux | grep redis | grep server|grep "$FLAGEID" | grep -v grep | grep -v .sh| wc -l)
	if [[ "$isAliveStr" -lt 1 ]];then
#	  startRedis="$BASEDIR/src/redis-server $BASEDIR/redis.conf"
#		echo "启动redis"
#		$startRedis
		gotErr 3
	fi
	if [[  "$isAliveStr" -gt 1 ]];then
		gotErr 3
	fi

}


#处理连接数
function getConnNum(){
	CURNUM=$(netstat -apn | grep $FLAGEID | grep ESTABLISHED  | wc -l)
}

#ps aux 4是内存 累加4的值
function getMemory(){
	CURNUM=$(ps aux | grep $FLAGEID |awk 'BEGIN{sum=0}{sum+=$4}END{print sum}')
}

#ps aux 3是CPU 累加3的值
function getCPU(){
	CURNUM=$(ps aux | grep $FLAGEID |awk 'BEGIN{sum=0}{sum+=$3}END{print sum}')
}

#function get_redis_stat {
#	if (( VERBOSE == 1 )) ; then
#		REDIS_STAT=$(./cmd/linux/redis-stat.sh -f "$BASEDIR" -p "$PORT" -v)
#	else
#		REDIS_STAT=$(./cmd/linux/redis-stat.sh -f "$BASEDIR" -p "$PORT")
#	fi
#}

#ps -eo pid,etime 是查询进程运行时间
function getRuntime(){
	CURNUM=$(ps -eo pid,etime | grep $FLAGEID |awk '{if($1=='$FLAGEID') print $2}')
}

#ps -eo pid,lstart是查询进程的开始时间
function getStarttime(){
	CURNUM=$(ps -eo pid,lstart | grep $FLAGEID |awk '{if($1=='$FLAGEID') print $2 ,$3 ,$4 ,$5 ,$6}')
}
#依据传入的参数值来判断我们要监控的服务是什么
#然后通过各个函数获取到具体的值
#值之间的
function analysisStat(){

	if [ "$CONN" -eq 1 ];then
		getConnNum
		parseFileds "ConnectionNum" $CONNMIN $CONNMAX
	fi
	if [ "$MEMORY" -eq 1 ];then
		getMemory
		parseFileds "Memory" $MEMORYMIN $MEMORYMAX
	fi
	if [ "$CPU" -eq 1 ];then
		getCPU
		parseFileds "CPU" $CPUMIN $CPUMAX
	fi
	
	if [ "$FLAGEOPID" -eq 1 ];then
		CURNUM=$FLAGEID
		parseFileds "FLAGEPID" $CURNUM $CURNUM
	fi

	if [ "$RUNTIME" -eq 1 ];then
			getRuntime
			parseTimeFileds "RUNTIME" $RUNTIME $RUNTIME		
	fi
	if [ "$STARTTIME" -eq 1 ];then
			getStarttime
			parseTimeFileds "STARTTIME" $STARTTIME $STARTTIME		
	fi
		
	if [[ "$SLOW_QUERY" -eq 1 ]] ; then
    slow_query_script="$(cd `dirname $0`;pwd)/check_redis_slow_query.sh"
		SLOW_RESULT=`$slow_query_script -f "$BASEDIR" -t "$THRESHOLD" -c "$LIMIT" -p "$PORT" -a "$AUTHEN"`
		RETURN_CODE=$?
		if (( RETURN_CODE == 0 )) ; then
			CURNUM=0
			parseFileds "Redis慢查询" $SLOW_QUERY_MIN $SLOW_QUERY_MAX
		elif ((RETURN_CODE == 3 )) ; then
			CURNUM=-1
			WranResultStr="${WranResultStr}Redis慢查询无法获取到慢查询的值"
			if [[ ${quota} != "" ]]; then
        	    quota="${quota},"
	    fi

      quota="${quota}Redis慢查询"
      QUOTASTR="${QUOTASTR}Redis慢查询=无法获取到慢查询的值"
      SLOW_RESULT=""
    else
    COUNT=$(echo $SLOW_RESULT| awk -F '<<COUNT>>' '{print $1}')
		SLOW_RESULT=$(echo $SLOW_RESULT| awk -F '<<COUNT>>' '{print $2}')
		CURNUM=${COUNT}
		parseFileds "Redis慢查询" $SLOW_QUERY_MIN $SLOW_QUERY_MAX
		fi
	fi
}

function parseTimeFileds(){
	val1=$(echo "$CURNUM $2")
	val2=$(echo "$CURNUM $3")
  DataResultStr="$DataResultStr $1=$CURNUM;$2;$3;0;0"
}
#CURNUM			当前值
#WARNLIMIT 		告警的上限
#ERRORLIMIT 	异常的上限
#判断以上三个值并拼接结果字符串
function parseFileds(){
	val1=$(echo "$CURNUM $2"| awk '{if($1<=$2){print 1}else{print 0}}')
	val2=$(echo "$CURNUM $3"| awk '{if($1<=$2){print 1}else{print 0}}')

	DataResultStr="$DataResultStr $1=$CURNUM;$2;$3;0;0"
	if [ $val1 -eq 1 ];then
		return 0
	elif [[ $val1 -eq 0 && $val2 -eq 1 ]];then
		if [[ ${WranResultStr} != "" ]]; then
			WranResultStr="${WranResultStr},"
		fi

		WranResultStr="${WranResultStr}$1当前值为${CURNUM}超过告警值${2}"

		if [[ ${quota} != "" ]]; then
			quota="${quota},"
		fi

		quota="${quota}$1"

		QUOTASTR="${QUOTASTR}$1=$1当前值为${CURNUM}超过告警值${2} "

		return 1
	else
		if [[ ${ErrorResultStr} != "" ]]; then
			ErrorResultStr="${ErrorResultStr},"
		fi
		ErrorResultStr="${ErrorResultStr}$1当前值为${CURNUM}超过紧急值${3}"

		if [[ ${quota} != "" ]]; then
			quota="${quota},"
		fi

		quota="${quota}$1"

		QUOTASTR="${QUOTASTR}$1=$1当前值为${CURNUM}超过紧急值${3} "
		
		return 2
	fi
}

#分析结果 给出给出状态
function analysisResult(){
	if [[ "$WranResultStr" == "" && "$ErrorResultStr" == "" ]];then
		gotErr 0
	elif [[ "$ErrorResultStr" == "" ]];then
		gotErr 1
	else
		gotErr 2
	fi
}

#输出错误信息并且退出程序
function showHelp(){
	if [ "$1" != "" ];then
		echo "请输入$1"
	fi
	echo "check_redis.sh 可以监听本地的redis的状态 参数如下"
	echo "check_redis.sh [-w 连接数,CPU,内存,慢查询] [-c 连接数,CPU,内存,慢查询] [-p <port>] [-a <password>] [-b <path>]"
	echo "-w 表示监控警告的值"
	echo "-c 表示异常值"
	echo "-t 设置记录Redis慢查询语句的执行时间阈值,默认为10000微秒"
	echo "-p 设置监听Redis数据库的端口,默认为6379"
  echo "-l 设置Redis记录慢查询语句的数目,超过此数值将删除最久的记录,默认为128"
	echo "-a 设置Redis认证密码,默认为空"
  echo "-b redis-cli可执行程序的路径"
  echo "-v 设置redis-stat脚本输出详细信息"
	exit 1
}


#检查参数是不是数字
function isNumber(){
	isNum=$(echo "$1" | awk '{print($0~/^([0-9])+[\.]?([0-9])?$/)?1:0}')
	return $isNum
}

function isLarge(){

	isNumber $1
	if [[ $? -eq 0 ]]; then
		return 1
	fi

	isNumber $2
	if [[ $? -eq 0 ]]; then
		return 1
	fi

	isLarge=$(echo "$1 $2"| awk '{if($1>=$2){print 1}else{print 0}}')
	if [ $isLarge -eq 1 ];then
		return 0
	else
		return 1
	fi
}

function checkARG(){
	if [[ "$2" != "" && "$3" != "" ]];then
		isLarge "$3" "$2"
		if [[ $? -eq 1 ]]; then
			return 1
		else
			$1=1
		fi
	fi
	return 0
}

#检查参数是否合法
#即参数是否是小数和整数
#对于守护进程的选择 这个值可以不验证
function checkALL(){
	if [[ "$CONNMIN" != "" || "$CONNMAX" != "" ]];then
		if [[ "$CONNMAX" == "" || "$CONNMIN" == "" ]]; then
			return 1
		fi

		isLarge "$CONNMAX" "$CONNMIN"
		if [[ $? -eq 1 ]]; then
			return 1
		else
			CONN=1
		fi
	fi
	if [[ "$CPUMIN" != "" || "$CPUMAX" != "" ]];then
		if [[ "$CPUMAX" == "" || "$CPUMIN" == "" ]]; then
			return 1
		fi

		isLarge "$CPUMAX" "$CPUMIN"
		if [[ $? -eq 1 ]]; then
			return 1
		else
			CPU=1
		fi
	fi
	if [[ "$MEMORYMIN" != "" || "$MEMORYMAX" != "" ]];then

		if [[ "$MEMORYMAX" == "" || "$MEMORYMIN" == "" ]]; then
			return 1
		fi

		isLarge "$MEMORYMAX" "$MEMORYMIN"
		if [[ $? -eq 1 ]]; then
			return 1
		else
			MEMORY=1
		fi
	fi

	if [[ "$SLOW_QUERY_MIN" != "" || "$SLOW_QUERY_MAX" != "" ]] ; then
		if [[ "$SLOW_QUERY_MAX" == "" || "$SLOW_QUERY_MIN" == "" ]] ; then
			return 1
		fi

		isLarge "$SLOW_QUERY_MAX" "$SLOW_QUERY_MIN"

		if [[ $? -eq 1 ]] ; then
			return 1
		else
			SLOW_QUERY=1
		fi
	fi
	return 0
}

function parseARG(){
	if [ $1 -eq 1 ];then
 		CONNMIN=$(echo $2 | awk -F ',' '{print $1}' | sed "s/[^0-9]//g")
 		CPUMIN=$(echo $2 | awk -F ',' '{print $2}' | sed "s/[^0-9]//g")
 		MEMORYMIN=$(echo $2 | awk -F ',' '{print $3}' | sed "s/[^0-9]//g")
 		SLOW_QUERY_MIN=$(echo $2 | awk -F ',' '{print $4}' | sed "s/[^0-9]//g")
 	else
 		CONNMAX=$(echo $2 | awk -F ',' '{print $1}' | sed "s/[^0-9]//g")
 		CPUMAX=$(echo $2 | awk -F ',' '{print $2}' | sed "s/[^0-9]//g")
 		MEMORYMAX=$(echo $2 | awk -F ',' '{print $3}' | sed "s/[^0-9]//g")
 		SLOW_QUERY_MAX=$(echo $2 | awk -F ',' '{print $4}' | sed "s/[^0-9]//g")
 	fi
}

while getopts ":w:c:f:t:l:b:p:a:hv" arg
do
	case $arg in
		w)
			parseARG 1 "$OPTARG"
			;;
		c)
			parseARG 2 "$OPTARG"
			;;
		h)
			showHelp
			;;
		t)
			THRESHOLD=$OPTARG
			;;
		l)	
			LIMIT=$OPTARG
			;;
		b)
			BASEDIR=$OPTARG
			;;
		p)
			PORT=$OPTARG
			;;
		a)
			AUTHEN=$OPTARG
			;;
		v)
			VERBOSE=1
			;;
		?) 
			showHelp
			;;
	esac
done

if [[ "$PORT" == "" ]];then
	showHelp "特征项"
fi

checkALL
if [[ $? == 1 ]];then
	showHelp "正确参数"
fi


#插件正题部分 
#确定存活的
#启动
#分析

#get_redis_stat
isAlive
analysisStat
analysisResult
